package cn.ac.cintcm.synonymous;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.apache.log4j.Logger;

public class WordEditCtl extends EditCtl {
    private static Logger logger = Logger.getLogger(EditCtl.class);
    private ResultTerms resultTerms;
    private Job job;
    private static WordEditCtl wec;
    
    public synchronized static WordEditCtl getInstance(DataSource ds, Job job, Dictionary dict) {
        if (wec == null || Config.reloaded) {
            wec = new WordEditCtl(ds, job, dict);
        }
        return wec;
    }
    
    public WordEditCtl(DataSource ds, Job job, Dictionary dict) {
        super(ds, dict);
        this.job = job;
        resultTerms = new ResultTerms();
        process();
    }

    public void process() {
        resultTerms.empty();
        for (int i = 1; i < ds.getLength(); i++) {
            Record r = job.process(i);
            addTerms(r.getFormal(), Record.FORMAL, ds.getRecordId(i));
            addTerms(r.getInForaml(), Record.ALIAS, ds.getRecordId(i));
            addTerms(r.getUnrecoginzed(), Record.UNRECOGNIZED, ds.getRecordId(i));
        }
    }

    public ResultTerms getResultTerms() {
        return resultTerms;
    }

    public void setResultTerms(ResultTerms resultTerms) {
        this.resultTerms = resultTerms;
    }
    
    public Message change(String word, String operation,
            String newTerm, String author) {
        Message m = null;
        if (word != null && !word.trim().equals("")) {
            if (operation != null && !operation.trim().equals("")) {
                Date date = new Date();
                char t = operation.charAt(0);
                switch (t){
                    case EditCtl.ADD_FORMAL:
                        Word w = new Word();
                        w.setName(word);
                        w.setAlias(false);
                        w.setCreated(date);
                        w.setAuthor(author);
                        m = dict.addWord(w, null);
                        dictEdited++;
                        logger.debug("adding formal:" + word);
                        break;
                    case EditCtl.ADD_INFORMAL:
                        m = dict.addWord(newTerm, word, author);
                        dictEdited++;
                        logger.debug("adding informal:" + word + "Formal name:" + newTerm);
                        break;                       
                    case EditCtl.DELETE_WORD:
                        modify(word, "", author);
                        m = new Message(word + Config.DELETE_WORD);
                        m.setSuccess(true);
                        logger.debug("deleting word:" + word);
                        break;
                    case EditCtl.DELETE_DICT_WORD:
                        m = dict.deleteWord(word);
                        StringBuilder sb = new StringBuilder();
                        sb.append(Config.DELETE_WORD);
                        sb.append(Config.FIELD_SEPERATOR);
                        sb.append(author);
                        sb.append(Config.FIELD_SEPERATOR);
                        sb.append(date);
                        sb.append(Config.FIELD_SEPERATOR);
                        sb.append(word);
                        logger.info(sb.toString());
                        dictEdited++;
                        logger.debug("deleting dictionary word:" + word);
                        break;
                    case EditCtl.MODIFY_WORD:
                        modify(word, newTerm, author);
                        m = new Message(word + Config.UPDATE_WORD);
                        m.setSuccess(true);
                        logger.debug("modifing word:" + word);
                }
            }
        }
        return m;
    }
    
    
    private synchronized void modify(String word, String newWord, String author) {
        Term term = resultTerms.getTerm(word);
        if (term != null) {
            String[] sources = term.getSourceList();
            if (sources != null) {
                for (String id : sources) {
                    String original = ds.getSynonymous(Integer.parseInt(id));
                    if (original != null) {
                        String[] o = original.split(Config.getItemSeperatorPattern());
                        String s = EditCtl.modifyOriginal(id, author, o, word, newWord);
                        ds.getRecord(id)[ds.getSynonymousFieldIndex()] = s;
                        ds.getRecord(id)[ds.getFieldIndex(DataSource.EDITOR)] = author;
                        ds.getRecord(id)[ds.getFieldIndex(DataSource.DATE)] = new Date().toString();
                        dataSourceEdited++;
                    }
               }
            }
        }
    }

    private void addTerms(String[] terms, int type, String index) {
        if (terms != null) {
            for (int i = 0; i < terms.length; i++) {
                if (terms[i] != null && !terms[i].trim().equals("")) {
                    Term t = new Term(terms[i], (short) type);
                    t.addSource(index);
                    resultTerms.addTerms(t);
                }
            }
        }
        
    }
    
    public List<String[]> getSource(String word) {
        Term term = resultTerms.getTerm(word);
        List<String[]> sourceList = null;
        if (term != null) {
            sourceList = new ArrayList<String[]>();
            String[] data = new String[3];
            data[0] = DataSource.ID;
            data[1] = ds.getSynonymousField();
            data[2] = ds.getPrimaryField();
            sourceList.add(data);
            String[] sources = term.getSourceList();
            if (sources != null) {
                for (String id : sources) {
                    data = new String[3];
                    int index = Integer.parseInt(id);
                    data[0] = id;
                    data[1] = ds.getSynonymous(index);
                    data[2] = ds.getPrimary(index);
                    sourceList.add(data);
                }
            }
        }
       return sourceList;
    }
    
    public Message save() {
        process();
        return super.save();
    }

}
